home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / DBio.more / USeqPrint-tree.cpp < prev    next >
Text File  |  1996-07-05  |  42KB  |  1,627 lines

  1. // USeqPrint.tree.p 
  2. // d.g.gilbert, 1991 
  3.  
  4. /*
  5.  
  6. phylogenetic tree print
  7.  
  8. */
  9.  
  10. #pragma segment TreeDraw
  11.  
  12. CONST
  13.  
  14.     kTreePrintWindowRSRCID == 1030;
  15.  
  16.     kUnrooted == 1;
  17.     kCladogram == 2;
  18.     kPhenogram == 3;
  19.     kEurogram == 4;
  20.     kSwoopogram == 5;
  21.     kCurvogram == 6;
  22.     kDefaultTreeStyle == kPhenogram;
  23.  
  24. // TTreePrintDocument -----------------------------------------------
  25.  
  26.  
  27. pascal void TTreePrintDocument::ITreePrintDocument(OSType fileType, treeData,
  28.                         Handle        params; TFile itsFile)
  29. VAR  
  30.     aStr: string[80];
  31.     i    : integer;
  32.     TFile        aFile;
  33. {
  34.     fTreeData= NULL;
  35.     fParams= NULL;
  36.     fTreePrintView = NULL;
  37.     
  38.     if ((treeData!=NULL)) FailOsErr( HandToHand( treeData)); //Dup it so we own it
  39.     fTreeData= treeData; //may be nil if reading from file...
  40.     if ((params!=NULL))
  41.         FailOsErr( HandToHand( params))
  42.     else {
  43.         /*temp fix dummy param file...
  44.             Style Clado
  45.             GRows Horiz 
  46.         */
  47.         //- aStr= 'Style (*Clado)GRows (*Horiz)0'; 
  48.         aStr= '^^0'; 
  49.         i= length(aStr);  aStr[i]= ((char)(0));
  50.         i= pos('^',aStr); aStr[i]= ((char)(13));
  51.         i= pos('^',aStr); aStr[i]= ((char)(13));
  52.         params= Handle(NewString(aStr));
  53.         FailNIL( params);
  54.         CharsPtr((*params))^[0]= ' ';
  55.         }
  56.     fParams= params;
  57.     
  58.     /*---
  59.     New(aFile);
  60.     aFile->IFile(...);
  61.     aname= parentDoc.name + '.dotplot';
  62.     vol= parentdoc.vol;
  63.     dirid= parentdoc.dirid;
  64.     err= aFile->SpecifyWithTrio( name/vol/dirid);
  65.     ----*/
  66.     aFile= NewFile(fileType, kSAppSig, kUsesDataFork, kUsesRsrcFork, !kDataOpen, !kRsrcOpen);
  67.     IFileBasedDocument(aFile, fileType);
  68.     fSavePrintInfo = FALSE; //was TRUE;
  69. }
  70.  
  71. pascal TFile TTreePrintDocument::DoMakeFile(itsCommandNumber:CommandNumber); // override 
  72. {
  73.     DoMakeFile= NewFile(fScrapType, gApplication->fCreator, kUsesDataFork, kUsesRsrcFork, 
  74.                                                 !kDataOpen, !kRsrcOpen);
  75. }
  76.  
  77. pascal void TTreePrintDocument::FreeData(void)
  78. {
  79.     //- if ((fTreePrintView!=NULL)) fTreePrintView->Free(); */ /*??
  80.     fTreeData= DisposeIfHandle( fTreeData);
  81.     fParams= DisposeIfHandle( fParams);
  82. }
  83.  
  84.  
  85. pascal void TTreePrintDocument::Free(void) // override 
  86. {
  87.     FreeData();
  88.     inherited::Free();
  89. }
  90.  
  91.  
  92.  
  93. pascal void TTreePrintDocument::DoMakeViews(Boolean forPrinting) // override 
  94. VAR
  95.         TWindow        aWindow;
  96.         Point        minSize;
  97.         Point        maxSize;
  98.         vSize     : Vpoint;
  99.         TStdPrintHandler        aHandler;
  100. {
  101.  
  102.     aWindow = gViewServer->NewTemplateWindow(kTreePrintWindowRSRCID, this);
  103.     FailNil(aWindow);
  104.     
  105.     fTreePrintWind= TTreePrintWind(aWindow);
  106.     fTreePrintWind->ITreePrintWind();
  107.  
  108.     fTreePrintView = TTreePrintView(aWindow->FindSubView('PrVw'));
  109.     FailNil(fTreePrintView);
  110.  
  111.     fTreePrintView->fStylePop= TPopup(aWindow->FindSubView('pSTL'));
  112.     fTreePrintView->fHoriz= TRadio(aWindow->FindSubView('rHOR'));
  113.     //- fTreePrintView->fVert= TRadio(aWindow->FindSubView('rVER')); 
  114.     fTreePrintView->fFixed= TCheckBox(aWindow->FindSubView('cFIX'));
  115.     fTreePrintView->fNodeLen= TCheckBox(aWindow->FindSubView('cNDL'));
  116.     fTreePrintView->fNodeCluster= TCluster(aWindow->FindSubView('node'));
  117.     fTreePrintView->fRedrawBut= TButton(aWindow->FindSubView('bRDR'));
  118.     
  119.     if (fTreePrintView->fStylePop == NULL) 
  120.         fTreePrintView->fStyle= kDefaultTreeStyle
  121.     else
  122.         fTreePrintView->fStyle= fTreePrintView->fStylePop->GetCurrentItem();  
  123.  
  124.     fTreePrintWind->fStylePop= fTreePrintView->fStylePop;
  125.     fTreePrintWind->fRedrawBut= fTreePrintView->fRedrawBut;
  126.     fTreePrintWind->fGrowCluster= TCluster(aWindow->FindSubView('grow'));
  127.     fTreePrintWind->fNodeCluster= TCluster(aWindow->FindSubView('node'));
  128.     
  129.     fTreePrintView->fScroller = fTreePrintView->GetScroller(TRUE);
  130.             //fix so prefview scroll bar shows
  131. /*-    if ((fTreePrintView->fScroller!=NULL)) 
  132.             fTreePrintView->fScroller.fScrollLimit.v= 500;*/ 
  133.  
  134.         //! get initial calc of data 
  135.     fTreePrintView->CalcTree();
  136.             
  137.     // set window's resize limits so it can't become wider than the TreePrintview's edge 
  138.     /*---
  139.     WITH aWindow->fResizeLimits){
  140.         minSize = topLeft;
  141.         maxSize = botRight;
  142.         }
  143.     WITH maxSize)h = Min( 2 + fTreePrintView->fSize.h + kSBarSizeMinus1, h);
  144.     aWindow->SetResizeLimits(minSize, maxSize);
  145.     -----*/
  146.     
  147.     vsize.h= maxSize.h;
  148.     vsize.v= maxSize.v;
  149.     if ((fTreePrintView->fScroller!=NULL)) 
  150.         fTreePrintView->fScroller->SetScrollLimits(vsize, kDontRedraw);
  151.          
  152.     ShowReverted();  //!!!
  153.  
  154. }
  155.  
  156.  
  157. pascal void TTreePrintDocument::UntitledName(Str255 VAR noName) // override 
  158. {
  159.     noName= 'Untitled Tree';
  160.     //- inherited::UntitledName( noName); 
  161.     /*------
  162.     noName= Concat(fParentDoc.(*fTitle)^,' Tree'); 
  163.     if ((fWindowList != NULL) && (fWindowList.GetSize > 0))         
  164.         TWindow(fWindowList->First())->SetTitle(noName);
  165.     ----*/
  166. }
  167.  
  168.  
  169. /*
  170. PICT file has the following format:
  171.   Data Fork:
  172.     (a)  kMacdrawHeaderSize (512 bytes) == nulls
  173.     (b)  The rest => PICTure of window
  174.  
  175.  Resource Fork:
  176.     nothing, yet
  177. */
  178.  
  179.  
  180.  
  181. pascal void TTreePrintDocument::DoNeedDiskSpace(TFile itsFile,
  182.                                                             long VAR dataForkBytes, rsrcForkBytes)
  183. {
  184.     //)!get Print record requirements 
  185.     //- inherited::DoNeedDiskSpace(dataForkBytes, rsrcForkBytes); 
  186.     
  187.     dataForkBytes = dataForkBytes + kMacdrawHeaderSize  /*+ sizeof window pict */;
  188.     
  189.     /*-- if you really want to know pict size:
  190.     fTreePrintView->WriteToDeskScrap(); 
  191.     len= fTreePrintView->GivePasteData( NULL, 'PICT');
  192.     ----*/
  193.     /*---
  194.     rsrcForkBytes = rsrcForkBytes + kRsrcTypeOverhead + kRsrcOverhead + sizeof(DocState);
  195.     ---*/
  196. }
  197.  
  198.  
  199.  
  200.     
  201. pascal void TTreePrintDocument::DoRead(aFile:TFile; Boolean forPrinting) // override 
  202. VAR
  203.         longint        numChars;
  204.         hData    : Handle;
  205.         err        : OSErr;        
  206.         p            : CharsPtr;
  207. {    
  208.     //-- inherited::DoRead(aRefNum, rsrcExists, forPrinting);)!read print info stuff
  209.     // This is a Write-Only document == PICT of output drawing, no reading... ?
  210. }
  211.  
  212.  
  213.  
  214. pascal void TTreePrintDocument::DoWrite(TFile aFile, Boolean makingCopy)
  215. VAR
  216.         longint        len, count;
  217.         hPict            : handle;
  218.         header        : packed array [1..kMacdrawHeaderSize] of char;
  219.         fi                : FailInfo;
  220.  
  221.     pascal void HdlDoWrite(OSErr error, long message)
  222.     {
  223.         if (hPict != NULL) DisposHandle( hPict);
  224.     }
  225.  
  226. {
  227.     //- inherited::DoWrite(aRefNum, makingCopy);     --)NO write print info stuff
  228.  
  229.     fTreePrintView->WriteToDeskScrap();
  230.     
  231.     hPict= NewHandle(0);
  232.     CatchFailures(fi, HdlDoWrite);
  233.     len= fTreePrintView->GivePasteData( hPict, 'PICT');
  234.     if ((len > 0)) {
  235.         fillchar(header, kMacdrawHeaderSize, ((char)(0)));  
  236.         count = kMacdrawHeaderSize;
  237.         FailOSErr( aFile->WriteData( &header, count));
  238.         count= len;
  239.         HLock(hPict);
  240.         FailOSErr( aFile->WriteData( ptr((*hPict)), count));
  241.         HUnlock(hPict);    
  242.         }
  243.     Success(fi);
  244.     DisposHandle( hPict);
  245. }
  246.  
  247.  
  248. // TTreePrintWind ------------------------- 
  249.  
  250. pascal void TTreePrintWind::ITreePrintWind(void)
  251. {
  252.     IPrefWindow();
  253.     fWantSave= TRUE; 
  254. }
  255.  
  256. pascal void TTreePrintWind::SetPrefID(void) /* override */ 
  257. {
  258.     gPrefWindID= kTreePrintWindowRSRCID; gPrefWindName= 'TTreePrintWind';
  259. }
  260.  
  261. pascal void TTreePrintWind::DoEvent(EventNumber eventNumber, 
  262.                                             TEventHandler        source; TEvent event) // override 
  263. VAR
  264.         TTreePrintView        aTreePrintView;    
  265.         
  266.      pascal void RedoTree(void)
  267.      {
  268.          aTreePrintView->CalcTree();
  269.          aTreePrintView->ForceRedraw();
  270.      }
  271.      
  272. {
  273.     aTreePrintView= TTreePrintDocument(fDocument).fTreePrintView;
  274.     switch (eventNumber) {
  275.          
  276.         mPopupHit    : if ((source == fStylePop)) RedoTree
  277.             else inherited::DoEvent(eventNumber,source, event); 
  278.             
  279.         mButtonHit: if ((source == fRedrawBut)) RedoTree
  280.             else inherited::DoEvent(eventNumber,source, event); 
  281.             
  282.         mClusterHit: if ((source == fNodeCluster) || (source == fGrowCluster) 
  283. ) RedoTree
  284.             else inherited::DoEvent(eventNumber,source, event); 
  285.             
  286.         //dialogView eats all mEditTextHits -- 
  287.  
  288.         otherwise
  289.             inherited::DoEvent(eventNumber,source, event); 
  290.         }
  291. }
  292.  
  293.  
  294.  
  295.  
  296. // TTreePrintView -------------------------------------
  297.  
  298.  
  299.  
  300. pascal void TTreePrintView::ITreePrintView( TTreePrintDocument itsDocument, Boolean forClipboard)
  301. VAR
  302.         itsSize        : VPoint;
  303.         aHandler    : TTreePrintHandler;
  304.         sd                : SizeDeterminer;
  305. {
  306.     SetVPt(itsSize, kMaxCoord, kMaxCoord);
  307.     if (forClipboard)
  308.         sd = sizeVariable
  309.     else
  310.         sd = sizeFillPages;
  311.     IView(itsDocument, NULL, gZeroVPt, itsSize, sd, sd);
  312.     fScroller = NULL;
  313.     fStyle= kDefaultTreeStyle; 
  314.     fTreePrintDocument = itsDocument;
  315.  
  316.     fTreeData= itsDocument->fTreeData;
  317.     fParams    = itsDocument->fParams;
  318.     fRoot= NULL;
  319.     
  320. #if FALSE                                        //!!! Need to handle this
  321.     if (forClipboard) fWouldMakePICTScrap = TRUE;
  322. #endif
  323.  
  324.     if (!forClipboard) {
  325.         New(aHandler);
  326.         FailNil(aHandler);
  327.         aHandler->ITreePrintHandler(itsDocument, this, 
  328.                                     !kSquareDots,  
  329.                                   kFixedSize,            // horizontal page size is fixed 
  330.                                   kFixedSize);            // vertical page size is fixed 
  331.         }
  332. }
  333.  
  334.  
  335.  
  336. pascal void TTreePrintView::Initialize(void) // override 
  337. {
  338.     fScroller = NULL;
  339.     fRoot= NULL;
  340.     fStyle= kDefaultTreeStyle; 
  341.     fTreePrintDocument= NULL;
  342.     fTreeData= NULL;
  343.     fParams= NULL;
  344.     fMinSize= gZeroVPt;
  345.     inherited::Initialize();
  346. }
  347.  
  348. pascal void TTreePrintView::DoPostCreate(TDocument itsDocument) // override 
  349. VAR
  350.         TTreePrintHandler        aHandler;
  351. {    
  352.     inherited::DoPostCreate( itsDocument);
  353.     fTreePrintDocument = TTreePrintDocument(itsDocument);
  354.     fTreeData= TTreePrintDocument(itsDocument).fTreeData;
  355.     fParams     = TTreePrintDocument(itsDocument).fParams;
  356.     New(aHandler); FailNil(aHandler);
  357.     aHandler->ITreePrintHandler(itsDocument, this, !kSquareDots, // does not have square dots 
  358.                               kFixedSize,  kFixedSize);         
  359. }
  360.  
  361.  
  362. pascal void TTreePrintView::Free(void) // override 
  363. {
  364.     FreeData();
  365.     inherited::Free();
  366. }
  367.  
  368.  
  369.  
  370. pascal void TTreePrintHandler::ITreePrintHandler(TDocument itsDocument, TView itsView,
  371.                                             Boolean itsSquareDots, itsHFixedSize, itsVFixedSize)
  372. {
  373.     IStdPrintHandler( itsDocument, itsView,itsSquareDots,itsHFixedSize,itsVFixedSize);
  374.  
  375. }
  376.  
  377. pascal VCoordinate TTreePrintHandler::BreakFollowing(VHSelect vhs,
  378.                                          VCoordinate        previousBreak;
  379.                                          Boolean VAR automatic) // override 
  380. //from TStdPrintHandler->BreakFollowing(); Called from fView->DoBreakFollowing(), 
  381. VAR
  382.         VHSelect        orthoVHS;
  383.         VCoordinate        rowTop, maxVpage, endPage, newLoc;
  384.         integer        rowHeight, ngroup, i;
  385.         fi        : FontInfo;
  386.         done    : boolean;
  387. {
  388.  
  389.     BreakFollowing= inherited::BreakFollowing(vhs, previousBreak, automatic);
  390.     
  391. /*********
  392.     orthoVHS = gOrthogonal[vhs];
  393.     automatic = TRUE;
  394.     endPage =  fViewPerPage.vh[orthoVHS];
  395.  
  396.     if ((orthoVHS == v)) {
  397.         /*! we maybe need to calc this for each page, 
  398.             since # of kParagraph spaces can differ per page */
  399.         maxvpage = endPage;
  400.      
  401.         SetPortTextStyle(gPrintNameStyle);
  402.         GetFontInfo(fi);
  403.         rowHeight= fi.ascent+fi.descent+fi.leading;
  404.         rowTop = kTop;
  405.         ngroup = fAlnList->GetSize();
  406.         i= 0;
  407.         do {
  408.             endPage= rowTop;
  409.             i= i+1;
  410.             rowtop = rowtop + rowHeight + kRowLeading;
  411.             if ((i=ngroup)) {
  412.                 rowTop= rowTop + kParagraph;
  413.                 i= 0;
  414.                 }
  415.             done= rowTop >= maxvpage;
  416.         } while (!(done));
  417.         }
  418.         
  419.     newLoc = Min(previousBreak + endPage, fPrintExtent.botRight.vh[orthoVHS]);
  420.     BreakFollowing = newLoc;
  421. *****/
  422. }
  423.  
  424.  
  425.  
  426. CONST
  427.     maxnch == 30;
  428.     
  429. TYPE
  430.     plotstring == STRING[maxnch];   
  431.                 
  432.     nodeptr == ^node;
  433.     nodeHandle == ^nodeptr;
  434.     node == RECORD
  435.         /*b*/ next, back : nodeHandle;
  436.         /*b*/ tip             : Boolean;
  437.         /*b*/ nayme         : plotstring;
  438.         /*r*/ tipsabove     : short;  
  439.         /*b*/ xcoord, ycoord, userlen : REAL;
  440.         }
  441.             
  442. VAR //globals for DrawGram.... fold into locals as time permits
  443.         PicRect, PicFrame    : Rect;
  444.         treeXmin, treeYmin, treeXmax, treeYmax, 
  445.         Real        picXscale, picYscale; //plot2pict scale factors
  446.         integer        QDstemunit;
  447.         PicFirst    : boolean;
  448.  
  449.  
  450.  
  451. pascal void TTreePrintView::ForEachNodeDo( pascal void DoThis( aNode: UNIV Handle));
  452.     pascal void ToEachNode( nodeHandle p)
  453.     nodeHandle        VAR  pp ;
  454.     { 
  455.          if ((p!=NULL)) {
  456.              if (!(*p)->tip) {
  457.                 pp = (*p)->next;
  458.                 while ( pp != p){
  459.                     ToEachNode ((*pp)->back);
  460.                     pp = (*pp)->next;
  461.                     }
  462.                 }
  463.             DoThis( Handle(p));
  464.             }
  465.     }
  466. {
  467.     ToEachNode( NodeHandle(fRoot));
  468. }
  469.     
  470.  
  471. pascal void TTreePrintView::FreeData(void)
  472.     pascal void disposeTree(void)
  473.         pascal void DisposeNode( nodeHandle aNode)
  474.         { 
  475.             DisposHandle( Handle(aNode));
  476.         }
  477.     {
  478.         ForEachNodeDo( DisposeNode);
  479.     }
  480. {
  481.     DisposeTree();
  482.     fRoot= NULL;
  483. }
  484.  
  485.  
  486. procedure map2pic(real x,y, integer VAR h,v)
  487. begin
  488.     h= round( PicRect.left + (x-treeXmin) * picXscale);   
  489.     v= round( PicRect.top  + (treeYmax-y) * picYscale); 
  490.  
  491.     /*-----
  492.     WITH PicFrame){
  493.         if (picFirst then begin
  494.             left= h; right= h;
  495.             top= v; bottom= v;
  496.             picFirst= FALSE;
  497.             end
  498.         else {
  499.             left    = min(left, h);
  500.             right    = max(right,h);
  501.             top        = min(top,v);
  502.             bottom= max(bottom,v);
  503.             }
  504.         }
  505.     ----*/
  506. end;
  507.  
  508. function QDfontHeight: integer;
  509. var  fi: fontInfo;
  510. begin
  511.     getFontInfo(fi);
  512.     QDfontHeight= fi.ascent + fi.descent + fi.leading;
  513. end;
  514.  
  515. CONST
  516.     k90deg        == 1;
  517.     k180deg     == 2;
  518.     k270deg     == 3;
  519.     k0deg            == 0;
  520.  
  521. pascal void locateStr( integer h, v, rot,  str255 s, Rect VAR theRect)
  522. var  fi: fontInfo;  integer w, d, rotnum,
  523. {
  524.     rotnum= ((rot+44) % 360) / 90;
  525.     getFontInfo(fi);
  526.     d =  fi.ascent + fi.descent + fi.leading ;
  527.     w =  stringwidth(s) ;
  528.     CASE (rotnum) OF
  529.         k0deg, k180deg    :    SetRect( theRect, h, v, h + w, v + d);
  530.         k90deg, k270deg    : SetRect( theRect, h, v, h + d, v + w);
  531.         }
  532. }
  533.  
  534. CONST
  535.     kVertical == 0;
  536.     kHorizontal == 1;
  537.   
  538.     kWeighted == 0; 
  539.     kIntermediate == 1; 
  540.     kCentered == 2; 
  541.     kInner == 3;
  542.     kVshaped == 4;
  543.     
  544.  
  545. pascal void TTreePrintView::CalcTree(void)
  546.  
  547. pascal void CalcGram( Rect frame, 
  548.                     integer        theStyle, grows, nodeposition; 
  549.                     boolean        fixedsize, uselengths;
  550.                     hcFile VAR treefile, parmfile)
  551.         
  552. /* Version 3.3.  Copyright (c) 1986, 1990 by Joseph Felsenstein and
  553.     Christopher A. Meacham.
  554.     Permission is granted to copy, distribute, and modify this
  555.     program provided that (1) this copyright message is not removed
  556.     and (2) no fee is charged for this program. 
  557.     
  558.     hacked w/ a macheté by d.gilbert, June 1990:
  559.     -- dropped a plotters but hp
  560.     -- replaced NEW with NewPtr and DisposeTree
  561.     -- dropped all font stuff
  562.     -- replaced all file i/o with pointer i/o
  563.     -- dropped all interactive stuff
  564.          and replaced w/ parmfile reader
  565.     -- parmfile format:
  566.         -- 1 space b/n param name_value, uppercase is minimum abbrev.
  567.         Grow Horizontal/Vertical
  568.         Style Cladogram/Phenogram/Eurogram/Swoopogram/curVogram
  569.         Uselengths Yes/No
  570.         Rotate 95.0
  571.         Depth    1.23
  572.         Length 1.23
  573.         Nodelength 1.23
  574.         Position kIntermediate/kWeighted/kCentered/kInner/kVshaped
  575.  
  576.     */
  577.  
  578. CONST 
  579.    //- maxnch == 30; 
  580.     pointCh == '.';
  581.     pi == 3.141592653;
  582.     epsilon == 0.00001;
  583.         pendown == TRUE;
  584.         penup        == FALSE;
  585.     
  586.          //paramfile keys 
  587.         
  588.         //Used letters: ABCDEFGhijkLmNoPqRSTUvwxyz 
  589.         
  590.         kStyle                == 'S';    //Style == Unrooted/Clado/Swoopo/Euro/Pheno/Curvo
  591.     
  592.         kPlotNodeNum    == 'B'; 
  593.         kUnitPicScale == 'E';
  594.         
  595.             //Rooted tree params 
  596.         kUseLengths        == 'U';    //Use lengths= Yes/No
  597.         kFixedSize        == 'F';    //Fixed size
  598.         kGrows                 == 'G';    /*GRows == Horiz/Vert*/         
  599.         kRotateLabel    == 'R';    //Rotate label
  600.         kTreeDepth         == 'D';    //Depth of tree
  601.         kStemLength        == 'L';    //Length of stem
  602.         kNodeSpace         == 'N';    //Node space
  603.         kNodePosition == 'P';    //Position of node
  604.             
  605.   //- TYPE 
  606.     //- growth == integer; -- (vertical, horizontal);
  607.     //- treestyle == integer; -- (unrooted, cladogram, phenogram, curvogram, eurogram, swoopogram);
  608.         //- labelorient == (fixed, radial, along); 
  609.  
  610. /******
  611.     plotstring == STRING[maxnch];   
  612.                     
  613.     nodeptr == ^node;
  614.         nodeHandle == ^nodeptr;
  615.     node == RECORD
  616.       /*b*/ next, back : nodeHandle;
  617.       /*b*/ tip             : Boolean;
  618.       /*b*/ nayme         : plotstring;
  619.          /*r*/ tipsabove     : short;  
  620.       /*b*/ xcoord, ycoord, userlen : REAL;
  621.       }
  622. *******/
  623.  
  624. VAR
  625.     ntips, nextnode, nextnext,
  626.         short        numtochange, oldx, oldy, nmoves, payge ;
  627.         /*plotNodeNum,*/ haslengths : Boolean;
  628.         // fixedSize , uselengths: boolean;
  629.         unitPicScale,
  630.         xmargin, ymargin, topoflabels, rightoflabels, leftoflabels, tipspacing,
  631.       scale, nodespace, stemlength, treedepth, xsize, ysize 
  632.       /* labelheight, */ /* labelrotation,*/  /*expand,  rooty*/ : REAL;
  633.     //- grows : growth; 
  634.     //- theStyle : treestyle; 
  635.     //- root, where : nodeHandle;
  636.     //- nodeposition : integer;*/ /*(kWeighted, kIntermediate, kCentered, kInner, kVshaped);
  637.         
  638.  
  639.  
  640.   pascal void uppercase (char VAR ch )
  641.   { 
  642.     if (((ch >= 'a') && (ch <= 'z'))) ch = ((char)(ORD(ch) - 32)); 
  643.   }  
  644.  
  645.     pascal void getch (char VAR c )     // get next nonblank character 
  646.     {  
  647.         do {
  648.             if (hcEOLn(treefile)) c= hcRead(treefile); //if (hcReadLN(treefile)!='');
  649.             c= hcRead(treefile);
  650.         } while (!(c != ))' ';
  651.         if ((c == ((char)(0)))) c= ';'; //our terminator...
  652.     }  
  653.  
  654.  
  655.   pascal void treeread(void)
  656.     // read a tree from the treefile and set up nodes and pointers 
  657.     char        VAR ch ;
  658.                 char        quote;
  659.                 NodeHandle        aRoot;
  660.                 
  661.     pascal void addelement (nodeHandle VAR p , nodeHandle q )
  662.       /* read in and add next part of tree, it will be node p
  663.         and will be hooked to pointer q */
  664.       nodeHandle        VAR pfirst ;
  665.         short        n ;
  666.         Boolean        notlast ;
  667.                 done    : boolean;
  668.                 
  669.       pascal void processlength(nodeHandle p )
  670.         short        VAR digit, ordzero ;
  671.           REAL        valyew, divisor ;
  672.           Boolean        pointread ;
  673.       { 
  674.         ordzero = ORD('0');
  675.         pointread = FALSE;
  676.         valyew = 0.0;
  677.         divisor = 1.0;
  678.         getch(ch);
  679.         digit = ORD(ch)-ordzero;
  680.         while ( ((digit >= 0) && (digit <= 9)) || (ch=pointCh)){
  681.           if (ch == pointCh) pointread = TRUE
  682.           else {
  683.             valyew = valyew*10.0 + digit;
  684.             if (pointread) divisor = divisor*10.0;
  685.             }
  686.           getch(ch);
  687.           digit = ORD(ch)-ordzero;
  688.           }
  689.            (*p)->userlen = valyew/divisor;
  690.       } // processlength 
  691.  
  692.     {  
  693.       nextnode = nextnode + 1;
  694.             Handle(p) = NewHandle(sizeof(node)); 
  695.       if (ch == '(') {
  696.         (*p)->tip = FALSE;
  697.         (*p)->tipsabove = 0;
  698.         pfirst = p;
  699.         notlast = TRUE;
  700.         while ( notlast){
  701.                     Handle((*p)->next) = NewHandle(sizeof(node));
  702.           p = (*p)->next;
  703.                     nextnext= nextnext + 1;
  704.           (*p)->tip = FALSE;
  705.           getch (ch);
  706.           addelement ((*p)->back, p);
  707.           (*pfirst)->tipsabove = (*pfirst)->tipsabove + (*p)->(*back)->tipsabove;
  708.           if ((ch == ')') || (ch == ';')) {
  709.             notlast = FALSE;
  710.             do {  getch (ch);
  711.             } while (!((ch == ))':') || (ch == ',') || (ch == ')') || (ch == ';');
  712.             }
  713.           }
  714.         (*p)->next = pfirst;
  715.         p = pfirst;
  716.         }      else {
  717.         (*p)->tip = TRUE;
  718.         (*p)->tipsabove = 1;
  719.         ntips = ntips + 1;
  720.         /*---
  721.                 if (((ch == '''') || (ch='"'))) {
  722.                     quote= ch;
  723.           if (hcEOLn(treefile)) ch= hcRead(treefile);  
  724.           ch= hcRead(treefile);
  725.                     }                
  726.                 else --*/
  727.                 quote= ((char)(0));
  728.         n = 0;
  729.         do {
  730.                     if ((ch == '_') && (quote <= ' ')) ch = ' ';
  731.                     if (n < maxnch) { n= n+1; (*p)->nayme[n] = ch; }
  732.           if (hcEOLn(treefile)) ch= hcRead(treefile);
  733.                     ch= hcread(treefile);
  734.                 //- if ((quote > ' ')) done= (ch == quote) else 
  735.                     done= (ch == ':') || (ch == ',') || (ch == ')') || (ch == ';');
  736.         } while (!(done));
  737.                 (*p)->nayme[0]= ((char)(n));  
  738.         }
  739.       if (ch == ':') processlength (p)
  740.                               else haslengths = haslengths && (q == NULL);
  741.       (*p)->back = q;
  742.     } // addelement 
  743.  
  744.   {  
  745.     haslengths = TRUE;
  746.     ntips = 0;
  747.     nextnode = 0; nextnext= 0;
  748.     getch (ch);
  749.         aRoot= NULL;
  750.     addelement (aRoot, NULL);
  751.         NodeHandle(fRoot)= aRoot;
  752.         if (hcReadln(treefile) != '') ;
  753.     //- uselengths = haslengths;
  754.         if (!haslengths) uselengths= FALSE;
  755.   } // treeread 
  756.  
  757.  
  758.   pascal void initialparms(void)
  759.     
  760.         pascal void plotrparms(void)//for Macintosh
  761.         { 
  762.             PicRect= PicFrame;
  763.             InsetRect(PicRect, 10,10);
  764.             /*- ??? invert to collect TRUE frame.. 
  765.             with PicRect do 
  766.                 SetRect( PicFrame, right,bottom, left, top);
  767.             ---*/
  768.             WITH PicRect){
  769.                 xsize = (right-left);  
  770.                 ysize = (bottom-top);  
  771.                 }
  772.             picXscale= 1.0;  
  773.             picYscale= 1.0; 
  774.             QDstemunit= 8;
  775.             treeXmin= 0.0;
  776.             treeYmin= 0.0;
  777.             treeXmax= 1.0;
  778.             treeYmax= 1.0;
  779.         }  
  780.             
  781.  {  
  782.     plotrparms();
  783.         
  784.         fixedSize= TRUE;
  785.          fPlotNodeNum= FALSE;
  786.         unitPicScale= 50;  //< useroption
  787.         
  788.       xmargin = 0.08 * xsize;
  789.     ymargin = 0.08 * ysize;
  790.         nextnode= 0;
  791.         nextnext= 0;
  792.  
  793.    //-  grows = kVertical;
  794.     fLabelrotation = 45.0;
  795.     nodespace = 3.0;
  796.     stemlength = 0.05;
  797.     treedepth = 0.5/0.95;
  798.   } 
  799.  
  800.  
  801.  
  802.   pascal void FindTreeStyle(void)
  803.   char        VAR key, ch ;   boolean done,
  804.   { 
  805.         //- theStyle= kCladogram; */ /*Default
  806.         done= hcEOF(parmfile);
  807.         
  808.         while ( !done){
  809.             //read parameter key/name
  810.             do { key= hcRead(parmfile); until (key > ' ') or hcEOLn(parmfile);
  811.             //skip rest of parameter name...
  812.             do { ch= hcread(parmfile); until (ch <= ' ') or hcEOLn(parmfile);
  813.     
  814.             uppercase(key);
  815.             if ((key == kStyle)) {
  816.                 done= TRUE;
  817.                 ch= hcread(parmfile);
  818.                 uppercase (ch);
  819.                 switch (ch) {
  820.                     'C' : theStyle = kCladogram;
  821.                     'P' : theStyle = kPhenogram;
  822.                     'E' : theStyle = kEurogram;
  823.                     'S' : theStyle = kSwoopogram;
  824.                     'V' : theStyle = kCurvogram;
  825.                     'U' : theStyle = kUnrooted;
  826.                     }
  827.                 }
  828.             if (hcReadln(parmfile) != '') ;
  829.             done= done || hcEOF(parmfile);
  830.             }
  831.         hcRewind( parmfile);
  832.   } 
  833.     
  834.     
  835.   pascal void getparms(void)
  836.     // get from user the relevant parameters for the plotter and diagram 
  837.   char        VAR key, ch ; 
  838.             Boolean        ok ;  
  839.             x    : real;
  840.   { 
  841.     //rely on treeread to set uselengths
  842.     if (uselengths) nodeposition = kIntermediate
  843.     else nodeposition = kVshaped;
  844.     
  845.     while not hcEOF(parmfile) do begin
  846.       //read parameter key/name
  847.         repeat key= hcRead(parmfile); until (key > ' ') or hcEOLn(parmfile);
  848.         //skip rest of parameter name...
  849.         repeat      ch= hcread(parmfile);
  850.       until (ch <= ' ') or hcEOLn(parmfile);
  851.  
  852.         uppercase(key);
  853.     switch (key) {
  854.         
  855.       kGrows: {  //! note change in documentation 
  856.                 ch= hcread(parmfile);
  857.                 uppercase(ch);
  858.                 case ch of
  859.                     'H' : grows = kHorizontal;
  860.                     'V' : grows = kVertical;
  861.                     end();
  862.                 }
  863.                 
  864.       kUseLengths: {
  865.                 ch= hcread(parmfile);
  866.                 uppercase (ch);
  867.                 if haslengths then CASE ch OF
  868.                     'Y': begin uselengths= TRUE;
  869.                              nodeposition= kIntermediate;
  870.                              end();
  871.                     'N': begin uselengths= FALSE;
  872.                              nodeposition= kVshaped;
  873.                            end();
  874.                       end();
  875.         }
  876.                 
  877.       kFixedSize: {
  878.                 ch= hcread(parmfile);
  879.                 uppercase (ch);
  880.                 switch (ch) {
  881.                     'Y': fixedSize= TRUE;
  882.                     'N': fixedSize= FALSE;
  883.                     end();
  884.         }
  885.                 
  886.             kUnitPicScale    :     
  887.          begin
  888.                  hcReadReal(parmfile, unitPicScale);
  889.                  end();
  890.  
  891.       kPlotNodeNum: {
  892.                 ch= hcread(parmfile);
  893.                 uppercase (ch);
  894.                 switch (ch) {
  895.                     'Y': fPlotNodeNum= TRUE;
  896.                     'N': fPlotNodeNum= FALSE;
  897.                     end();
  898.         }
  899.  
  900.       kRotateLabel: {
  901.                 hcREADReal(parmfile, x);
  902.                 fLabelrotation= x;
  903.         }
  904.  
  905.           kTreeDepth: {
  906.         hcReadReal(parmfile, treedepth);
  907.         }
  908.                 
  909.       kStemLength: {
  910.                 hcReadReal(parmfile, x);
  911.                 if (x >= 0.0) && (x < 0.9) then stemlength = x;
  912.                 }
  913.                 
  914.       kNodeSpace: {
  915.         hcReadReal(parmfile, x);
  916.         if (x != 0.0) then nodespace = 1.0/x;
  917.         }
  918.                 
  919.       kNodePosition: {
  920.                 ch= hcread(parmfile);
  921.                 uppercase(ch);
  922.         switch (ch) {
  923.           'W' : nodeposition = kWeighted;
  924.           'I' : nodeposition = kIntermediate;
  925.           'C' : nodeposition = kCentered;
  926.           'N' : nodeposition = kInner;
  927.           'V' : nodeposition = kVshaped
  928.           }
  929.         }
  930.                 
  931.       }
  932.         if (hcReadln(parmfile) != '') ;
  933.         end();
  934.   } // getparms 
  935.  
  936.  
  937.  
  938.  
  939.   pascal void calculate(void)
  940.     // compute coordinates for tree 
  941.     VAR 
  942.             sum, tipx, maxtextlength, textlength,
  943.             stemdep, stem1dep,
  944.       REAL        firstlet, maxheight, fontheight, angle ;
  945.       short        i ;
  946.  
  947.     pascal void calctraverse (nodeHandle p , REAL lengthsum )
  948.       // traverse to establish initial node coordinates 
  949.       REAL        VAR x1, y1, x2, y2, x3, w1, w2, sumwx, sumw, nodeheight ;
  950.         nodeHandle        pp, plast ;
  951.     { 
  952.       if (p == NodeHandle(fRoot)) nodeheight = 0.0
  953.       else if (uselengths) nodeheight = lengthsum + (*p)->userlen
  954.              else nodeheight = 1.0;
  955.       if (nodeheight > maxheight) maxheight = nodeheight;
  956.       if ((*p)->tip) {
  957.         (*p)->xcoord = tipx;
  958.         if (uselengths) (*p)->ycoord = nodeheight
  959.         else (*p)->ycoord = 1.0;
  960.         tipx = tipx + tipspacing;
  961.         }      else {
  962.         sumwx = 0.0;
  963.         sumw = 0.0;
  964.         pp = (*p)->next;
  965.         x3 = 0.0;
  966.         do {
  967.           calctraverse ((*pp)->back, nodeheight);
  968.           sumw = sumw + (*pp)->(*back)->tipsabove;
  969.           sumwx = sumwx + (*pp)->(*back)->tipsabove*(*pp)->(*back)->xcoord;
  970.           if (ABS((*pp)->(*back)->xcoord-0.5) < ABS(x3-0.5)
  971. ) x3 = (*pp)->(*back)->xcoord;
  972.           plast = pp;
  973.           pp = (*pp)->next;
  974.         } while (!(pp == p));
  975.         x1 = (*p)->(*next)->(*back)->xcoord;
  976.         x2 = (*plast)->(*back)->xcoord;
  977.         y1 = (*p)->(*next)->(*back)->ycoord;
  978.         y2 = (*plast)->(*back)->ycoord;
  979.         switch (nodeposition) {
  980.           kWeighted     : {
  981.             w1 = y1 - nodeheight;
  982.             w2 = y2 - nodeheight;
  983.             if ((w1 + w2) <= 0.0
  984. ) (*p)->xcoord = (x1 + x2)/2.0
  985.             else (*p)->xcoord = (w2*x1 + w1*x2)/(w1+w2);
  986.             }
  987.           kIntermediate     : (*p)->xcoord = (x1 + x2)/2.0;
  988.           kCentered             : (*p)->xcoord = sumwx/sumw;
  989.           kInner                 : (*p)->xcoord = x3;
  990.           kVshaped             : (*p)->xcoord = (x1 + x2 + (y1 - y2)/maxheight)/2.0
  991.           }
  992.         if (uselengths) (*p)->ycoord = nodeheight
  993.         else {
  994.           (*p)->ycoord = (x1 - x2 + y1 + y2)/2.0;
  995.           if (nodeposition == kInner) {
  996.             if (ABS(x1-0.5) > ABS(x2 - 0.5)) {
  997.               (*p)->ycoord = y1 + x1 - x2;
  998.               w1 = y2 - (*p)->ycoord;
  999.               }            else {
  1000.               (*p)->ycoord = y2 + x1 - x2;
  1001.               w1 = y1 - (*p)->ycoord;
  1002.               }
  1003.             if (w1 < epsilon) (*p)->ycoord = (*p)->ycoord - ABS(x1-x2);
  1004.             }
  1005.           }
  1006.         }
  1007.     } // traverse 
  1008.  
  1009.         pascal lengthtext(plotstring pstring , nchars : short) : REAL;
  1010.              short        VAR i, j, code ;
  1011.                     REAL        cfix, sumlength, heightfont, widthfont ;
  1012.         {  
  1013.              sumlength = 0.0;
  1014.              FOR i = 1 TO nchars){
  1015.                     widthfont=  charwidth(pstring[i]);
  1016.                     sumlength = sumlength + widthfont;
  1017.                     }
  1018.              lengthtext = sumlength;
  1019.         } // lengthtext 
  1020.  
  1021.  
  1022.     pascal void getTextLength( nodeHandle aNode)
  1023.     {
  1024.         if ((*aNode)->tip) {
  1025.             firstlet   = lengthtext ((*aNode)->nayme, 1);
  1026.             textlength = lengthtext ((*aNode)->nayme, length((*aNode)->nayme));
  1027.             if (textlength > maxtextlength) maxtextlength = textlength;
  1028.             }
  1029.     }
  1030.  
  1031.     pascal void setYcoord( nodeHandle aNode)
  1032.     {
  1033.         (*aNode)->ycoord = stemdep + stem1dep * ((*aNode)->ycoord - fRooty);
  1034.     }
  1035.  
  1036.   { // calculate 
  1037.     maxheight = 0.0;
  1038.     maxtextlength = 0.0;
  1039.     sum = 0.0;
  1040.     tipx = 0.0;
  1041.         ForEachNodeDo( getTextLength);
  1042.         
  1043.     fontheight = QDfontHeight;
  1044.     angle = pi*fLabelrotation/180.0;
  1045.     maxtextlength = maxtextlength/fontheight;
  1046.     textlength = textlength/fontheight;
  1047.     firstlet = firstlet/fontheight;
  1048.     if (ntips > 1) fLabelheight = 1.0/(nodespace*(ntips-1))
  1049.                              else fLabelheight = 1.0/nodespace;
  1050.     if (angle < (pi/6.0)) tipspacing = (nodespace
  1051.                   + COS(angle)*(maxtextlength-0.5))*fLabelheight
  1052.     else if (ntips > 1) tipspacing = 1.0/(ntips-1.0)
  1053.       else tipspacing = 1.0;
  1054.     topoflabels = fLabelheight*(1.0 + SIN(angle)*(maxtextlength-0.5)
  1055.                           + COS(angle)*0.5);
  1056.     rightoflabels = fLabelheight*(COS(angle)*(textlength-0.5) +SIN(angle)*0.5);
  1057.     leftoflabels = fLabelheight*(COS(angle)*firstlet*0.5+SIN(angle)*0.5);
  1058.     calctraverse (NodeHandle(fRoot), sum);
  1059.         
  1060.     fRooty = (*NodeHandle(fRoot))->ycoord;
  1061.         stemdep    = stemlength*treedepth;
  1062.         stem1dep= ((1.0-stemlength)*treedepth) / (maxheight-fRooty);
  1063.         ForEachNodeDo( setYcoord);
  1064.     fRooty = 0.0;
  1065.   } // calculate 
  1066.  
  1067.  
  1068.     procedure findPicScale;
  1069.     var
  1070.             integer        fhigh, wmax, dmax, h, v, i, j;
  1071.             firstNode,firstTip     : boolean;
  1072.             theRect, textFrame    : rect;
  1073.  
  1074.         pascal void findRange( nodeHandle aNode)
  1075.         {
  1076.             if (firstNode) {
  1077.                 treeXmax= (*aNode)->xcoord; treeXmin= treeXmax;
  1078.                 treeYmax= (*aNode)->ycoord; treeYmin= treeYmax;
  1079.                 firstNode= FALSE;
  1080.                 }            else with (*aNode)^ do begin
  1081.                 if xcoord > treeXmax then treeXmax= xcoord
  1082.                   else if xcoord < treeXmin then treeXmin= xcoord;
  1083.                 if ycoord > treeYmax then treeYmax= ycoord
  1084.                   else if ycoord < treeYmin then treeYmin= ycoord;
  1085.                 }
  1086.                 
  1087.             if ((*aNode)->tip) {
  1088.                 locateStr( h, v, round(fLabelrotation), (*aNode)->nayme, theRect);
  1089.                 if (firstTip) { textFrame= theRect; firstTip= FALSE; }                else UnionRect( textFrame, theRect, textFrame);
  1090.                 if (grows == kVertical) h= textFrame.right+2 
  1091.                 else v= textFrame.bottom+2;
  1092.                 WITH theRect){
  1093.                     wmax= max(wmax, right-left);
  1094.                     dmax= max(dmax, bottom-top);
  1095.                     }
  1096.                 }
  1097.         }
  1098.             
  1099.     {
  1100.         firstTip = TRUE; 
  1101.         firstNode= TRUE;
  1102.         wmax= 0; dmax= 0; 
  1103.         h= 1; v= 1;
  1104.         ForEachNodeDo( findRange);
  1105.             
  1106.         if (FixedSize) { //set always TRUE ?!
  1107.             /*---
  1108.             picXScale= unitPicScale;
  1109.             picYscale= picXScale;
  1110.             ---*/
  1111.             fhigh= QDfontHeight + 5;
  1112.             if (grows == kVertical) {
  1113.                 WITH textFrame)OffsetRect( PicRect, 0, top);  
  1114.                 picXScale= (wmax+5)/*fhigh*/ / tipspacing;
  1115.                 picYscale= QDstemunit / stemlength;
  1116.                 }            else {
  1117.                 picXScale= QDstemunit / stemlength;
  1118.                 picYscale= (dmax+5)/*fhigh*/ / tipspacing;
  1119.                 }
  1120.             }            
  1121.         else {
  1122.             if (grows == kVertical) {
  1123.                 WITH textFrame)OffsetRect( PicRect, 0, top); 
  1124.                 }
  1125.             picXscale= 1.0;
  1126.             picYscale= picXscale;
  1127.             }
  1128.     }
  1129.     
  1130.  
  1131.   pascal void rescale(void)
  1132.     // compute coordinates of tree for plot or preview device 
  1133.     short        VAR i ;
  1134.       REAL        treeheight, treewidth, extrax, extray, temp ;
  1135.             
  1136.         pascal void scaleXY( nodeHandle aNode)
  1137.         {
  1138.             (*aNode)->xcoord = fExpand*((*aNode)->xcoord + leftoflabels);
  1139.             (*aNode)->ycoord = fExpand*((*aNode)->ycoord - fRooty);
  1140.       if (grows == kHorizontal) {
  1141.         temp = (*aNode)->ycoord;
  1142.         (*aNode)->ycoord = fExpand*treewidth-(*aNode)->xcoord;
  1143.         (*aNode)->xcoord = temp;
  1144.         }
  1145.       (*aNode)->xcoord = (*aNode)->xcoord + xmargin + extrax;
  1146.       (*aNode)->ycoord = (*aNode)->ycoord + ymargin + extray;
  1147.         }
  1148.         
  1149.         pascal void findTreeMax( nodeHandle aNode)
  1150.         {
  1151.             if ((*aNode)->ycoord > treeheight) treeheight = (*aNode)->ycoord;
  1152.         }
  1153.  
  1154.   { 
  1155.         treeheight = 0.0;
  1156.         ForEachNodeDo(findTreeMax);
  1157.         treeheight = treeheight + topoflabels;
  1158.         treewidth  = (ntips-1)*tipspacing + rightoflabels + leftoflabels;
  1159.         
  1160.     if (grows == kVertical) {  //! drop all of this !?
  1161.       fExpand = (xsize - 2*xmargin)/treewidth;
  1162.       if ((ysize - 2*ymargin)/treeheight < fExpand) 
  1163.                 fExpand = (ysize - 2*ymargin)/treeheight;
  1164.       extrax = (xsize - 2*xmargin - treewidth*fExpand)/2.0;
  1165.       extray = (ysize - 2*ymargin - treeheight*fExpand)/2.0;
  1166.       }    else {
  1167.       fExpand = (ysize - 2*ymargin)/treewidth;
  1168.       if ((xsize - 2*xmargin)/treeheight < fExpand) 
  1169.                 fExpand = (xsize - 2*xmargin)/treeheight;
  1170.       extrax = (xsize - 2*xmargin - treeheight*fExpand)/2.0;
  1171.       extray = (ysize - 2*ymargin - treewidth*fExpand)/2.0;
  1172.       }
  1173.             
  1174.         if (fixedSize) { //! always !?
  1175.             fExpand= 1.0;
  1176.             extrax= 0.0;
  1177.             extray= 0.0;
  1178.             }
  1179.             
  1180.         ForEachNodeDo(scaleXY);
  1181.             
  1182.     if (grows == kVertical) fRooty = ymargin + extray
  1183.                                          else fRooty = xmargin + extrax;
  1184.       findPicScale();   //!!!!
  1185.   } // rescale 
  1186.  
  1187.     PicFrame= frame;
  1188.     FindTreeStyle();
  1189.     treeread();
  1190.     initialparms();
  1191.     getparms();
  1192.     calculate();
  1193.     rescale();
  1194. } //calcGram
  1195.  
  1196. VAR
  1197.     fi    : fontInfo;
  1198.     hcFile        hcTree, hcParams;
  1199.     IDType        nodeID;
  1200.     Rect        frame;
  1201.     integer        grow, nodeposition;
  1202.     boolean        fixedsize, uselengths;
  1203. {
  1204. //-    SetPortTextStyle(gPrintNameStyle); < times-italic 
  1205.     SetPortTextStyle(gPrintNucStyle); //< helvetica ?
  1206.  
  1207.     if ((fRoot!=NULL)) FreeData;
  1208.     
  1209.     if (fStylePop == NULL) fStyle= kDefaultTreeStyle
  1210.     else fStyle= fStylePop->GetCurrentItem();  
  1211.     
  1212.     if (fHoriz == NULL) grow= kHorizontal
  1213.     else if (fHoriz.IsOn then grow= kHorizontal
  1214.     else grow= kVertical;
  1215.  
  1216.     nodeId= fNodeCluster->GetCurrentChoice();
  1217.     if nodeID == 'nInt') nodeposition= kIntermediate
  1218.     else if nodeID == 'nWgt' then nodeposition= kWeighted
  1219.     else if nodeID == 'nCen' then nodeposition= kCentered
  1220.     else if nodeID == 'nInn' then nodeposition= kInner
  1221.     else if nodeID == 'nVsh' then nodeposition= kVshaped
  1222.     else nodeposition= kIntermediate;
  1223.  
  1224.     fixedSize= fFixed->IsOn();
  1225.     uselengths= fNodeLen->IsOn();
  1226.  
  1227.     hcOpen(hcTree, fTreeData);
  1228.     hcOpen(hcParams, fParams);
  1229.     this->GetQDExtent( frame);
  1230.     InsetRect( frame, 25, 50);
  1231.  
  1232.     CalcGram( frame, fStyle, grow, nodeposition, fixedsize, uselengths,
  1233.                         hcTree, hcParams);
  1234. }
  1235.  
  1236.  
  1237.  
  1238. pascal void TTreePrintView::Draw(VRect area)    
  1239. VAR
  1240.         integer        grows;
  1241.         
  1242.     pascal void DrawGram(void)
  1243.     CONST 
  1244.      //- maxnch == 30; 
  1245.         //- pi == 3.141592653; 
  1246.         epsilon == 0.00001;
  1247.         pendown == TRUE;
  1248.         penup        == FALSE;
  1249.  
  1250.   pascal void plottree (nodeHandle p, q )
  1251.     // plot part or all of tree on the plotting device 
  1252.     CONST 
  1253.             segments == 40;
  1254.     VAR 
  1255.             REAL        x1, y1, x2, y2, x3, y3, f, g, h, fract, minny, miny ;
  1256.             nodeHandle        pp ;
  1257.  
  1258.         pascal void plot(boolean penIsDown, REAL xabs, yabs ) 
  1259.         integer        VAR  h, v;
  1260.         {  
  1261.             map2pic( xabs, yabs, h, v);
  1262.             if (penIsDown) LineTo( h,v)
  1263.             else MoveTo( h,v);
  1264.         }  
  1265.  
  1266.         pascal void SwoopoMe(void)
  1267.         integer        VAR  i;
  1268.         {
  1269.             if ((grows == kVertical) && (!(ABS(y1-y2) < epsilon))
  1270.             || ((grows == kHorizontal) && (!(ABS(x1-x2) < epsilon))) 
  1271. ) {
  1272.                 if (grows == kVertical) miny = (*p)->ycoord
  1273.                                                         else miny = (*p)->xcoord;
  1274.                 pp = (*q)->next;
  1275.                 while ( pp != q){
  1276.                     if (grows == kVertical) minny = (*pp)->(*back)->ycoord
  1277.                                                             else minny = (*pp)->(*back)->xcoord;
  1278.                     if (minny < miny) miny = minny;
  1279.                     pp = (*pp)->next;
  1280.                     }
  1281.                 if (grows == kVertical) fract = 0.3333*(miny-y1)/(y2-y1)
  1282.                     else fract = 0.3333*(miny-x1)/(x2-x1);
  1283.                 FOR i = 1 TO segments){
  1284.                     f = i/segments;
  1285.                     if (f < fract) g = f/fract
  1286.                         else g = (f-fract)/(1.0-fract);
  1287.                     if (f < fract) h = fract*SQRT(1.0-(1.0-g)*(1.0-g))
  1288.                         else h = fract + (1.0-fract)*(1.000001 - SQRT(1.000001-g*g));
  1289.                     if (grows == kVertical) {
  1290.                         x3 = x1*(1.0-f)+x2*f;
  1291.                         y3 = y1 + (y2 - y1)*h;
  1292.                         }                    else {
  1293.                         x3 = x1 + (x2 - x1)*h;
  1294.                         y3 = y1*(1.0-f)+y2*f;
  1295.                         }
  1296.                     plot (pendown, x3, y3);
  1297.                     }
  1298.                 }
  1299.         } //swoopoMe
  1300.             
  1301.         pascal void curvoMe(void)
  1302.         integer        VAR i;
  1303.         {
  1304.             FOR i = 1 TO segments){
  1305.                 f = i/segments;
  1306.                 g = i/segments;
  1307.                 h = 1.0 - SQRT(1.0-g*g);
  1308.                 if (grows == kVertical
  1309. ) {
  1310.                     x3 = x1*(1.0-f)+x2*f;
  1311.                     y3 = y1 + (y2 - y1)*h;
  1312.                     }                else {
  1313.                     x3 = x1 + (x2 - x1)*h;
  1314.                     y3 = y1*(1.0-f)+y2*f;
  1315.                     }
  1316.                 plot (pendown, x3, y3);
  1317.                 }
  1318.         }
  1319.  
  1320.   {  
  1321.     x2 = ( (*p)->xcoord);
  1322.     y2 = ( (*p)->ycoord);
  1323.     if (p != NodeHandle(fRoot)) {
  1324.       x1 = ( (*q)->xcoord);
  1325.       y1 = ( (*q)->ycoord);
  1326.       plot (penup, x1, y1);
  1327.             
  1328.       switch (fStyle) {
  1329.             
  1330.                 kUnrooted,
  1331.         kCladogram     : plot (pendown, x2, y2);
  1332.                 
  1333.         kPhenogram     : {
  1334.           if (grows == kVertical) plot (pendown, x2, y1)
  1335.                  else plot (pendown, x1, y2);
  1336.           plot (pendown, x2, y2);
  1337.           }
  1338.                     
  1339.         kEurogram         : {
  1340.           if (grows == kVertical) plot (pendown, x2, (2*y1+y2)/3)
  1341.           else plot (pendown, (2*x1+x2)/3, y2);
  1342.           plot (pendown, x2,y2);
  1343.           }
  1344.                     
  1345.         kCurvogram     : curvoMe;
  1346.         kSwoopogram     : SwoopoMe;
  1347.         }
  1348.       }            
  1349.     else if ((fStyle != kUnrooted)) {
  1350.       if (grows == kVertical) {
  1351.         x1 = ( (*p)->xcoord);
  1352.         y1 = ( fRooty);
  1353.         }      else {
  1354.         x1 = ( fRooty);
  1355.         y1 = ( (*p)->ycoord);
  1356.         }
  1357.       plot (penup, x1, y1);
  1358.       plot (pendown, x2, y2);
  1359.       }
  1360.             
  1361.     if (!(*p)->tip) {
  1362.       pp = (*p)->next;
  1363.       while ( pp != p){
  1364.         plottree ((*pp)->back, p);
  1365.         pp = (*pp)->next;
  1366.         }
  1367.       }
  1368.   } // plottree 
  1369.  
  1370.         
  1371.   pascal void plotlabels(void)
  1372.     short        VAR i ;
  1373.          REAL        dx, dy, angle ;
  1374.       integer        nodenum;
  1375.             
  1376.         pascal void plottext(plotstring pstring ,  REAL x, y, rotate )
  1377.         integer        VAR   h, v;
  1378.         {  
  1379.             map2pic( x, y, h, v);
  1380.             textPicDraw( h, v, round(rotate), pstring);  
  1381.             //- UnionRect( PicFrame, gTextRect, PicFrame); << gTextRect supposed to come from textPicDraw
  1382.         }  
  1383.     
  1384.         pascal void PlotNodeLabel( nodeHandle aNode)
  1385.         VAR    
  1386.                 str255        nums;  
  1387.                 integer        h, v;
  1388.         {
  1389.             nodenum= nodenum+1;
  1390.       if ((*aNode)->tip) {
  1391.                 dx= 0; dy= 0;  //?
  1392.         dx = -fLabelheight*fExpand*0.70710*COS(angle+pi/4.0);
  1393.         dy =  fLabelheight*fExpand*(1.0-0.70710*SIN(angle+pi/4.0));
  1394.         if (grows == kVertical) plottext((*aNode)->nayme,
  1395.                  ((*aNode)->xcoord+dx),  ((*aNode)->ycoord+dy), fLabelrotation)
  1396.         else plottext((*aNode)->nayme, 
  1397.                         ((*aNode)->xcoord+dy), ((*aNode)->ycoord-dx), fLabelrotation);
  1398.                 }                
  1399.             else if (fPlotNodeNum) {   
  1400.                 numtostring( nodenum, nums);
  1401.                 map2pic( (*aNode)->xcoord, (*aNode)->ycoord, h, v);
  1402.                 moveto(h,v); 
  1403.                 drawstring( nums);            
  1404.                 }
  1405.         }
  1406.     
  1407.   {  
  1408.         nodenum= 0;
  1409.     angle = fLabelrotation*pi/180.0;
  1410.         ForEachNodeDo( PlotNodeLabel);
  1411.   } // plotlabels 
  1412.  
  1413.     {  
  1414.         PicFirst= TRUE;
  1415.         PlotTree (NodeHandle(fRoot), NodeHandle(fRoot));
  1416.         PlotLabels();        
  1417.     }
  1418.  
  1419. {
  1420.     inherited::Draw(area);
  1421. //-    SetPortTextStyle(gPrintNameStyle); < times-italic 
  1422.     SetPortTextStyle(gPrintNucStyle); //< helvetica ?
  1423.  
  1424.     if (fHoriz == NULL) grows= kHorizontal
  1425.     else if (fHoriz.IsOn then grows= kHorizontal
  1426.     else grows= kVertical;
  1427.  
  1428.     beginPicGroup(); 
  1429.     DrawGram();
  1430.     endPicGroup();
  1431. }
  1432.  
  1433.  
  1434.  
  1435. pascal void TTreePrintView::CalcMinFrame(VRect VAR minFrame)
  1436. VAR
  1437.     integer        nb;
  1438.     TScroller        aScroller;
  1439. {
  1440.     inherited::CalcMinFrame( minFrame);
  1441.     
  1442.     /******
  1443.     if ((fAlnList!=NULL) && (fAlnList.GetSize>0)) {
  1444.         if (fNbases == 0) then nb= TSequence(fAlnList->First()).fLength 
  1445.         else nb= fNbases;
  1446.         //this is a kludge...
  1447.         minsize.h= max(minsize.h, (15+min(40,nb))*12);
  1448.          minSize.v= max(minsize.v, (2 + (nb / 40)) * (fAlnList.GetSize * 14 + kParagraph));
  1449.         end();
  1450.     minSize.h= max(minSize.h, fMinSize.h);
  1451.     minSize.v= max(minSize.v, fMinSize.v);
  1452.     aScroller= GetScroller(TRUE);
  1453.     if ((ascroller!=NULL)) aScroller->SetScrollLimits(minSize, kDontRedraw);
  1454.     *******/
  1455. }
  1456.  
  1457.  
  1458.  
  1459.  
  1460. pascal void TTreePrintView::DoMenuCommand(CommandNumber aCommandNumber) // override 
  1461. {
  1462.     switch (aCommandNumber) {
  1463.         cCopy: {
  1464.                 this->WriteToDeskScrap(); 
  1465.                 gClipboardMgr->CheckDeskScrap(); //! this notifies app of changed scrap 
  1466.                 }
  1467.         otherwise
  1468.             inherited::DoMenuCommand(aCommandNumber);
  1469.         }
  1470. }
  1471.         
  1472. /*---------    
  1473. pascal void TTreePrintView::DoMenuCommand(CommandNumber aCommandNumber) // override 
  1474. {
  1475. VAR
  1476.         short        menu, item;
  1477.         MCEntryPtr        pMCEntry;
  1478.         RGBColor        theColor;
  1479.         StringHandle        pickerPrompt;
  1480. {
  1481.     switch (aCommandNumber) {
  1482.         cCut, cCopy:
  1483.             {
  1484.             New(TreePrintCutCopyCommand);
  1485.             FailNil(TreePrintCutCopyCommand);
  1486.             TreePrintCutCopyCommand->ITreePrintCutCopyCommand(aCommandNumber, this);
  1487.             DoMenuCommand = TreePrintCutCopyCommand;
  1488.             }
  1489.  
  1490.         case cPaste:
  1491.             {
  1492.             New(TreePrintPasteCommand);
  1493.             FailNil(TreePrintPasteCommand);
  1494.             TreePrintPasteCommand->ITreePrintPasteCommand(this);
  1495.             DoMenuCommand = TreePrintPasteCommand;
  1496.             }
  1497.  
  1498.         case cClear:
  1499.             {
  1500.             New(TreePrintClearCommand);
  1501.             FailNil(TreePrintClearCommand);
  1502.             TreePrintClearCommand->ITreePrintClearCommand(this);
  1503.             DoMenuCommand = TreePrintClearCommand;
  1504.             }
  1505.  
  1506.         default:
  1507.             {
  1508.             CommandToMenuItem(aCommandNumber, menu, item);
  1509.             if (menu == mColor) {
  1510.                 New(recolorCmd);
  1511.                 FailNil(recolorCmd);
  1512.                 pMCEntry = GetMCEntry(menu, item);
  1513.                 theColor = pMCEntry->mctRGB2;         
  1514.                 recolorCmd->IRecolorCmd(theColor, this);
  1515.                 DoMenuCommand = recolorCmd;
  1516.                 }            else
  1517.                 inherited::DoMenuCommand(aCommandNumber);
  1518.             }
  1519.     }                                 
  1520. }
  1521. ------*/
  1522.  
  1523.  
  1524. /*******
  1525. pascal TCommand TTreePrintView::DoMouseCommand(Point VAR theMouse, EventInfo VAR info,
  1526.                                    Point VAR hysteresis)
  1527. VAR
  1528.         FailInfo        fi;
  1529.  
  1530.     pascal void HdlInitCmdFailed(OSErr error, long message)
  1531.         {
  1532.         FreeIfObject(protoTreePrint);
  1533.         protoTreePrint = NULL;
  1534.         }
  1535.  
  1536.     {                    
  1537.  
  1538.     fClickPt = theMouse;
  1539.     if (palette->fCurrTreePrint > 0) { // draw mode
  1540.         FailSpaceIsLow();                                 // Make sure we aren't low on memory 
  1541.  
  1542.         Deselect();
  1543.  
  1544.         //Clone appropriate TreePrint
  1545.  
  1546.         protoTreePrint = TTreePrint(gTreePrintsArray[palette->fCurrTreePrint].Clone);
  1547.         FailNil(protoTreePrint);
  1548.  
  1549.         CatchFailures(fi, HdlInitCmdFailed);
  1550.         // Make sure cloning the TreePrint left us with enough memory to continue.
  1551.         FailSpaceIsLow();
  1552.  
  1553.         New(TreePrintSketcher);
  1554.         FailNil(TreePrintSketcher);
  1555.         TreePrintSketcher->ITreePrintSketcher(this, protoTreePrint, info.theOptionKey);
  1556.         Success(fi);
  1557.         DoMouseCommand = TreePrintSketcher;
  1558.         }            
  1559.         
  1560.     else {         //select mode
  1561.         TreePrintUnderMouse = NULL;
  1562.         fTreePrintDocument->EachVirtualTreePrintDo(CheckTreePrint);
  1563.  
  1564.         if (TreePrintUnderMouse == NULL)    {        //area select
  1565.             if (!info.theShiftKey)
  1566.                 Deselect();
  1567.             New(TreePrintSelector);
  1568.             FailNil(TreePrintSelector);
  1569.             TreePrintSelector->ITreePrintSelector(cMouseCommand, this);
  1570.             DoMouseCommand = TreePrintSelector;
  1571.             } 
  1572.  
  1573.         else {                                        //TreePrint select/move/...
  1574.             if (!(TreePrintUnderMouse->fIsSelected || info.theShiftKey))
  1575.                 Deselect();
  1576.  
  1577.             if (info.theShiftKey) {
  1578.                 TreePrintUnderMouse->fIsSelected = !TreePrintUnderMouse->fIsSelected;
  1579.                 if (TreePrintUnderMouse->fIsSelected)
  1580.                     TreePrintUnderMouse->Highlight(hlOff, hlOn)
  1581.                 else
  1582.                     TreePrintUnderMouse->Highlight(hlOn, hlOff);
  1583.                 }            else if (!TreePrintUnderMouse->fIsSelected)
  1584.                 {
  1585.                 TreePrintUnderMouse->fIsSelected = TRUE;
  1586.                 DoHighlightSelection(hlOff, hlOn);
  1587.                 }
  1588.  
  1589.             if (TreePrintUnderMouse->fIsSelected) {
  1590.                 New(TreePrintDragger);
  1591.                 FailNil(TreePrintDragger);
  1592.                 TreePrintDragger->ITreePrintDragger(this);
  1593.                 DoMouseCommand = TreePrintDragger;
  1594.                 }
  1595.             //else, fall-through, we return NULL
  1596.             }     
  1597.         }                     
  1598. }                                        
  1599. **********/
  1600.  
  1601.  
  1602.  
  1603. pascal void TTreePrintView::DoSetupMenus(void)
  1604.     {
  1605.         short        i;
  1606.         Boolean        anySelection;
  1607.         Boolean        haveMemory;
  1608.         MenuHandle        aMenuHandle;
  1609.         short        item;
  1610.         Str255        itemName;
  1611.  
  1612.  
  1613.     inherited::DoSetupMenus();
  1614.  
  1615.     anySelection = FALSE;
  1616.     haveMemory = !MemSpaceIsLow;
  1617.  
  1618.     Enable(cCopy, TRUE && haveMemory);
  1619. /*----    
  1620.     Enable(cCut, anySelection && haveMemory);
  1621.     if (haveMemory) CanPaste(kPrintClipType);
  1622.     Enable(cClear, anySelection);
  1623. -------*/
  1624. }             
  1625.  
  1626.